<template>
  <div>
    <div @keydown.enter="getList" class="search" @submit.native.prevent>
      <el-form :inline="true" :model="searchData">
        <el-form-item label="选择分组">
          <el-select v-model="searchData.group" filterable default-first-option placeholder="请选择组" clearable
            @change='change_selectGroup'>
            <el-option v-for="item in groups" :key="item" :label="item" :value="item">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="关键词">
          <el-input v-model="searchData.keyword" placeholder="关键词(标题、url)" clearable />
        </el-form-item>
        <el-form-item label="">
          <el-button type="primary" icon="el-icon-search" size="small" @click="getList">查询</el-button>
        </el-form-item>
        <el-form-item label="" v-if="$global.hasPermission('job/add')">
          <el-button type="primary" icon="el-icon-plus" @click="btnShowForm('add')">新增</el-button>
        </el-form-item>
      </el-form>
    </div>

    <el-table v-loading="listLoading" :data="list" element-loading-text="Loading" fit highlight-current-row>
      <el-table-column label="标题" prop="title" align="center">
        <template slot-scope="scope">
          <el-popover placement="top-start" title="" width="235" trigger="hover" :open-delay='300'>
            <div>
              <div> <span>创建时间：</span> <span style="color:#409eff">{{ scope.row.createTime }}</span></div>
              <div> <span>已执行次数：</span> <span style="color:#409eff">{{ scope.row.executionCount }}</span></div>
              <div> <span>启停状态：</span> <span :style="{ color: scope.row.isEnable ? '#409eff' : '#ff9966' }">{{
                scope.row.isEnable ? '启用' : '停用' }}</span></div>
              <div> <span>调度状态：</span> <span :style="{ color: scope.row.isScheduled ? '#409eff' : '#ff9966' }">{{
                scope.row.isScheduled ? '已调度' : '未调度' }}</span></div>
            </div>
            <div :style="{ color: scope.row.isEnable ? '#409eff' : '#888888' }" slot="reference">{{ scope.row.title }}
            </div>
          </el-popover>
        </template>
      </el-table-column>

      <el-table-column label="组" prop="group" align="center" />

      <el-table-column label="状态" align="center" width="45">
        <template slot-scope="scope">
          <div>
            <el-tooltip class="item" effect="dark"
              :content="scope.row.isEnable ? (scope.row.isScheduled ? '已调度' : '未调度') : '停用'" placement="top-start"
              :open-delay='300'>
              <span v-if="scope.row.isEnable && scope.row.isScheduled" style="color: #1ebf97;">🟢</span>
              <span v-else-if="scope.row.isEnable && !scope.row.isScheduled" style="color: #ff9966 ;">🟠</span>
              <span v-else style="color: #ff9966 ;">⚪</span>
            </el-tooltip>
          </div>
        </template>
      </el-table-column>

      <el-table-column label="内容" prop="content" align="center" width="140">
        <template slot-scope="scope">
          <el-tooltip class="item" effect="dark" :content="scope.row.content" placement="top-start" :open-delay='300'>
            <div>{{ scope.row.contentOmit }}</div>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column label="Cron" prop="cron" align="center" />
      <el-table-column label="创建人" prop="creator" align="center" width="80" />

      <el-table-column label="最近执行状态" prop="executionCount" align="center">
        <template slot-scope="scope">
          <div style="display: flex;" @click="log(scope.row.id)">
            <span class="recentStatus" v-for="item in scope.row.recentExecutionStatusArr"
              :class="{ recentStatus1: item, recentStatus0: !item }"></span>
          </div>
        </template>
      </el-table-column>

      <el-table-column label="最新执行结果" align="center" width="131">
        <template slot-scope="scope">
          <el-popover placement="top-start" title="" width="260" trigger="hover" :open-delay='300'>
            <div>
              <div> <span>最新执行时间：</span> <span style="color:#409eff">{{ scope.row.lastExecutionTimeDes }}</span></div>
              <div> <span>最新执行状态：</span> <span
                  :style="{ color: scope.row.lastExecutionStatus ? '#409eff' : '#ff9966' }">{{
                    scope.row.lastExecutionStatus ? '成功' : '失败' }}</span></div>
              <div> <span>最新执行结果：</span> <span style="color:#409eff">{{ scope.row.result }}</span></div>
            </div>
            <div :style="{ color: scope.row.lastExecutionStatus ? '#55a32f' : '#ce1212' }" slot="reference">{{
              scope.row.lastExecutionTime }}</div>
          </el-popover>
        </template>
      </el-table-column>

      <el-table-column label="下次执行时间" align="center" width="131">
        <template slot-scope="scope">
          <el-popover placement="top-start" title="" width="160" trigger="hover" :open-delay='300'
            v-if="scope.row.isEnable">
            <div>
              <div> <span></span> <span style="color:#409eff">{{ scope.row.nextExecutionTime }}</span></div>
            </div>
            <div :style="{ color: scope.row.executionExpired ? '#ff9966' : 'inherit' }" slot="reference">{{
              scope.row.nextExecutionTimeDes }}</div>
          </el-popover>
        </template>
      </el-table-column>

      <el-table-column label="最近失败时间" prop="lastFailureTime" align="center" width="95" />

      <el-table-column label="备注" prop="note" align="center">
        <template slot-scope="scope">
          <el-tooltip class="item" effect="dark" :content="scope.row.note" placement="top-start" :open-delay='300'>
            <div>{{ scope.row.noteOmit }}</div>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="200">
        <template slot-scope="scope">
          <el-button v-if="$global.hasPermission('job/update')" size="small" class="blackStyle" type="text"
            @click="btnShowForm('edit', scope.row)">修改</el-button>
          <el-button v-if="scope.row.isEnable && $global.hasPermission('job/enable')" size="small" class="blackStyle"
            type="text" @click="enable(scope.row)">停用</el-button>
          <el-button v-if="!scope.row.isEnable && $global.hasPermission('job/disable')" size="small" class="blackStyle"
            type="text" @click="enable(scope.row)">启用</el-button>
          <el-button v-if="$global.hasPermission('job/delete')" size="small" class="blackStyle" type="text"
            @click="deleteItem(scope.row.id)">删除</el-button>
          <el-button v-if="$global.hasPermission('job/getRecords')" size="small" class="blackStyle" type="text"
            @click="log(scope.row.id)">日志</el-button>
          <el-dropdown style="margin-left: 10px;">
            <el-button v-if="$global.hasPermission('job/once') || $global.hasPermission('job/copy')" size="small"
              class="blackStyle" type="text" style="color: #2367ad;">更多..</el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item @click.native="once(scope.row.id)">
                <el-button v-if="$global.hasPermission('job/once')" size="small" class="blackStyle"
                  type="text">立即执行一次</el-button>
              </el-dropdown-item>
              <el-dropdown-item @click.native="copy(scope.row.id)">
                <el-button v-if="$global.hasPermission('job/copy')" size="small" class="blackStyle"
                  type="text">Copy(新副本默认为停用)</el-button>
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination @current-change="currentChange" :page-size="searchData.pageSize" :total="totalCount"
      style="float: right; margin-top: 10px;" background layout="prev, pager, next">
    </el-pagination>


    <!-- form -->
    <el-dialog :title="(formDialog.type == 'add' ? '新增' : '修改')" :visible.sync="formDialog.show" width="55%"
      class="dialogClass" :close-on-click-modal="false">
      <el-form :model="form" class="form">
        <div style="display: flex;">
          <el-form-item label="标题" required label-width="80px" style="flex:6">
            <el-input v-model="form.title" placeholder="标题" clearable />
          </el-form-item>
          <el-form-item label="组" label-width="40px" style="flex:3">
            <el-select v-model="form.group" filterable allow-create default-first-option placeholder="若没有则在此新建"
              clearable>
              <el-option v-for="item in groups" :key="item" :label="item" :value="item">
              </el-option>
            </el-select>
          </el-form-item>
        </div>

        <div style="display: flex;">
          <el-form-item label="Cron" required label-width="80px" style="flex:6">
            <el-input v-model="form.cron" placeholder="Cron" @input="handleInputCron">
              <div slot="suffix">
                <el-popover placement="top-start" title="Cron表达式示例" width="235" trigger="click">
                  <div style="display:flex"><span style="width:40%;color:#409eff">0/2 * * * * ?</span>
                    <span>每两秒一次</span>
                  </div>
                  <div style="display:flex"><span style="width:40%;color:#409eff">0 0/1 * * * ?</span>
                    <span>每分钟一次</span>
                  </div>
                  <div style="display:flex"><span style="width:40%;color:#409eff">0 0 0/1 * * ?</span>
                    <span>每小时一次</span>
                  </div>
                  <div style="display:flex"><span style="width:40%;color:#409eff">0 0 1 * * ?</span>
                    <span>每天1点一次(24h制)</span>
                  </div>
                  <i slot="reference" class="el-icon-question"></i>
                </el-popover>
              </div>
            </el-input>

          </el-form-item>
          <el-form-item label="" label-width="7px" style="flex:3">
            <div class="cronDes">{{ formDialog.cronDes }}</div>
          </el-form-item>
        </div>

        <el-form-item label="任务类型" label-width="100px" required>
          <el-radio v-model="form.jobType" label="Url">请求URL</el-radio>
          <el-radio v-if="user.roleKey == '管理员'" v-model="form.jobType" label="Script">脚本</el-radio>
        </el-form-item>

        <el-form-item label="Url" v-if="form.jobType == 'Url'" required label-width="80px">
          <el-input v-model="form.content" placeholder="Url" clearable />
        </el-form-item>

        <el-form-item v-if="form.jobType == 'Script'" label="脚本内容" required label-width="80px">
          <el-input type="textarea" v-model="form.content" placeholder="脚本内容" :rows="3" clearable />
        </el-form-item>

        <el-form-item label="备注" label-width="80px">
          <el-input v-model="form.note" placeholder="备注" clearable />
        </el-form-item>

        <el-form-item label="日志保留天数" label-width="100px">
          <el-input v-model="form.logRetentionDays" placeholder="默认30天" type="number" />
        </el-form-item>

        <el-collapse>
          <el-collapse-item name="1" v-if="form.jobType == 'Url'">
            <template slot="title">
              <span style="color: #409eff;margin-left: 20px;">更多请求设置..</span>
            </template>
            <el-form-item label="请求方法" label-width="100px">
              <el-radio v-model="form.requestMethond" label="Get">Get</el-radio>
              <el-radio v-model="form.requestMethond" label="Post">Post</el-radio>
              <el-radio v-model="form.requestMethond" label="Put">Put</el-radio>
              <el-radio v-model="form.requestMethond" label="Delete">Delete</el-radio>
            </el-form-item>
            <el-form-item label="请求Header" label-width="100px">
              <el-input v-model="form.requestHeader" placeholder="key1: value1
key2: value2" clearable type="textarea" style="color: #3a8ee6;" :autosize="{ minRows: 1, maxRows: 4 }" />
            </el-form-item>
            <el-form-item label="请求Body" label-width="100px">
              <el-input v-model="form.requestBody" placeholder="Json字符串" clearable type="textarea"
                style="color: #3a8ee6;" :autosize="{ minRows: 1, maxRows: 4 }" />
            </el-form-item>
            <el-form-item label="失败重试(s)" label-width="100px">
              <el-input v-model="form.failureRetryPolicy" placeholder="失败重试间隔；逗号分隔的数值；单位：秒；示例：10,60,120">
                <div slot="suffix">
                  <el-popover placement="top-start" title="失败重试策略：" width="210" trigger="hover">
                    <div>逗号分隔的数值</div>
                    <div>单位：秒；示例：10,60,120</div>
                    <div>为空时则失败不会重试</div>
                    <i slot="reference" class="el-icon-question"></i>
                  </el-popover>
                </div>
              </el-input>
            </el-form-item>
            <el-form-item label="随机延迟(s)" label-width="100px">
              <el-input v-model="form.randomDelay" placeholder="单位：秒" clearable />
            </el-form-item>
          </el-collapse-item>

          <el-collapse-item name="2">
            <template slot="title">
              <span style="color: #409eff;margin-left: 20px;">更多通知设置..</span>
            </template>
            <el-form-item label="通知策略" label-width="100px">
              <el-radio v-for="item in noticePolicy" v-model="form.noticePolicy" :key="item.value" :label="item.value"
                :value="item.value">{{ item.displayName }}</el-radio>
            </el-form-item>
            <el-form-item label="期望结果" label-width="100px">
              <el-input v-model="form.expected" placeholder="返回结果值,支持Regex;为空时默认HTTP状态码=200为成功" clearable />
            </el-form-item>
            <el-form-item label="通知对象" label-width="100px">
              <el-input v-model="form.noticeObjects" placeholder="邮件：多个用逗号或分号隔开" clearable />
            </el-form-item>
          </el-collapse-item>
        </el-collapse>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submit" v-loading="formDialog.loading">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 日志 -->
    <el-drawer title="" :visible.sync="showRecord" direction="rtl" size="50%">
      <div style="height: 86vh;overflow: visible;margin:0 20px">
        <div @keydown.enter="getList" class="search">
          <el-form :inline="true" :model="searchDataRecord" @submit.native.prevent>
            <el-form-item label="">
              <el-checkbox v-model="searchDataRecord.onlyFailed" @change='changeOnlyFailed'>只显示失败任务日志</el-checkbox>
            </el-form-item>
          </el-form>
        </div>
        <el-table :data="records" v-loading="loadingRecords">
          <el-table-column property="createTime" label="日期" width="140"></el-table-column>
          <el-table-column label="是否成功" align="center" width="50">
            <template slot-scope="scope">
              <span :style="{ color: scope.row.isSuccess ? '' : '#ce1212' }">{{ scope.row.isSuccess ? '成功' : '失败'
                }}</span>
            </template>
          </el-table-column>
          <el-table-column property="result" label="返回结果">
            <template slot-scope="scope">
              <el-tooltip class="item" effect="dark" :content="scope.row.result" placement="top-start">
                <div>{{ scope.row.resultOmit }}</div>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column label="执行内容" prop="content" align="center" width="140">
            <template slot-scope="scope">
              <el-tooltip class="item" effect="dark" :content="scope.row.content" placement="top-start">
                <div>{{ scope.row.contentOmit }}</div>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column property="note" label="备注"></el-table-column>
          <el-table-column label="通知" align="center" width="60">
            <template slot-scope="scope">
              <el-button v-if="scope.row.hasNotice && $global.hasPermission('job/noticeDetails')" size="small"
                class="blackStyle" type="text" @click="getNotices(scope.row.id)">通知日志</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination @current-change="currentChangeRecord" :page-size="searchDataRecord.pageSize"
          :total="recordTotalCount" style="float: right; margin-top: 10px;" background layout="prev, pager, next">
        </el-pagination>
      </div>
    </el-drawer>
    <el-dialog title="通知日志" :visible.sync="showNotice" width="60%">
      <el-table :data="notices" v-loading="loadingNotice" style="min-height: 200px;">
        <el-table-column property="noticeStatus" label="状态" width="150"></el-table-column>
        <el-table-column property="noticeObject" label="发送到"></el-table-column>
        <el-table-column property="sentTime" label="发送时间"></el-table-column>
        <el-table-column property="sentResult" label="发送结果"></el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="showNotice = false">关 闭</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { getEnums, getUser } from '@/utils/auth'
export default {
  data() {
    return {
      list: null,
      listLoading: false,
      loadingRecords: false,
      loadingNotice: false,
      searchData: {
        pageIndex: 1,
        pageSize: 10,
      },
      totalCount: 0,
      form: {},
      formInit: { requestMethond: 'Get', noticePolicy: 0, jobType: 'Url' },
      formDialog: {
        title: '新增角色',
        show: false,
        type: 'add',
        loading: false,
        cronDes: '请先输入cron表达式',
      },
      listRole: [],
      showRecord: false,
      records: [],
      recordTotalCount: 0,
      searchDataRecord: {
        pageIndex: 1,
        pageSize: 10,
        jobId: 0,
        onlyFailed: false
      },
      groups: [],
      requestMethods: ['Get', 'Post', 'Put', 'Delete'],
      showNotice: false,
      notices: [],
      noticePolicy: [],
      user: {},
      handleInputCron : this.debounce(this.parseCron,500)
    }
  },
  created() {
    this.getList()
    this.getGroups()
    this.noticePolicy = getEnums()['noticePolicy']
    this.user = getUser()
  },
  methods: {
    getNotices(recordId) {
      let that = this
      that.notices = []
      this.showNotice = true
      this.loadingNotice = true
      that.$system
        .get('job/noticeDetails', { id: recordId })
        .then((res) => {
          that.notices = res
        })
        .catch((res) => { })
        .finally(() => {
          this.loadingNotice = false
        })
    },
    change_selectGroup() {
      this.getList()
    },
    copy(id) {
      let that = this
      this.$system
        .post('job/copy', { id: id })
        .then((res) => {
          this.$tip.success()
          that.getList()
        })
        .catch()
        .finally(() => {
          this.formDialog.loading = false
        })
    },
    getList() {
      let that = this
      that.listLoading = true
      that.$system
        .get('job/get', this.searchData)
        .then((res) => {
          this.list = res.list
          this.list.forEach((s) => {
            (s.contentOmit = this.$format.omit(s.content, 20)),
              (s.resultOmit = this.$format.omit(s.result, 20)),
              (s.noteOmit = this.$format.omit(s.note, 8)),
              (s.recentExecutionStatusArr = s.recentExecutionStatus.split("").map(char => char === "1")),
              (s.executionExpired = new Date(s.nextExecutionTime) < new Date(new Date() + 1000 * 10))
          })
          this.totalCount = res.totalCount
        })
        .catch((res) => { })
        .finally(() => {
          that.listLoading = false
        })
    },
    getGroups() {
      let that = this
      that.listLoading = true
      that.$system
        .get('job/GetGroups', that.searchDataRecord)
        .then((res) => {
          that.groups = res
        })
        .catch((res) => { })
        .finally(() => {
        })
    },
    getRecords() {
      let that = this
      that.loadingRecords = true
      that.$system
        .get('job/GetRecords', that.searchDataRecord)
        .then((res) => {
          this.records = res.list
          this.records.forEach(s => {
            s.resultOmit = this.$format.omit(s.result, 20)
            s.contentOmit = this.$format.omit(s.content, 20)
          });
          this.recordTotalCount = res.totalCount
        })
        .catch((res) => { })
        .finally(() => {
          that.loadingRecords = false
        })
    },
    changeOnlyFailed() {
      this.getRecords()
    },
    deleteItem(_id) {
      this.$confirm('确定删除该数据?', '', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.listLoading = true
          this.$system
            .delete('job/delete', { id: _id })
            .then((res) => {
              this.$tip.success()
              this.getList()
            })
            .catch(() => { })
            .finally(() => {
              this.listLoading = false
            })
        })
        .catch(() => { })
    },
    btnShowForm(type, item) {
      this.formDialog.type = type
      this.form = {}
      this.formDialog.show = true
      if (this.formDialog.type === 'edit') {
        this.form = this.$format.deepCopy(item)
        this.parseCron()
      } else {
        this.form = this.formInit
      }
    },
    currentChange(val) {
      this.searchData.pageIndex = val
      this.getList()
    },
    currentChangeRecord(val) {
      this.searchDataRecord.pageIndex = val
      this.getRecords()
    },
    submit() {
      // debugger
      let that = this
      this.formDialog.loading = true
      if (that.formDialog.type == 'edit') {
        this.$system
          .put('job/update', that.form)
          .then((res) => {
            this.$tip.success()
            that.formDialog.show = false
            that.getList()
          })
          .catch()
          .finally(() => {
            this.formDialog.loading = false
          })
      } else {
        this.$system
          .post('job/add', that.form)
          .then((res) => {
            this.$tip.success()
            that.formDialog.show = false
            that.getList()
          })
          .catch()
          .finally(() => {
            this.formDialog.loading = false
          })
      }
    },
    once(_id) {
      let that = this
      this.$system
        .post('job/once', { id: _id })
        .then((res) => {
          this.$tip.success()
          that.formDialog.show = false
          that.getList()
        })
        .catch()
        .finally(() => {
          this.formDialog.loading = false
        })
    },
    enable(row) {
      let that = this
      var api = row.isEnable ? 'job/disable' : 'job/enable'
      this.$system
        .put(api, { id: row.id, isEnable: !row.isEnable })
        .then((res) => {
          this.$tip.success()
          that.formDialog.show = false
          that.getList()
        })
        .catch()
        .finally(() => {
          this.formDialog.loading = false
        })
    },
    log(rowId) {
      let that = this
      this.searchDataRecord.jobId = rowId
      that.getRecords()
      that.showRecord = true
    },
    parseCron() {
      let that = this
      that.$system
        .get('job/ParseCron', { key: that.form.cron })
        .then((res) => {
          // debugger
          that.formDialog.cronDes = res
        })
        .catch((res) => { })
        .finally(() => {
        })
    },
    debounce(fn, duration = 300) {
      let timerId
      return function () {
        if (timerId) clearTimeout(timerId)
        timerId = setTimeout(() => {
          fn()
        }, duration);
      }
    },

  },

}
</script>

<style scoped>
.el-drawer__header {
  height: 36px;
  margin-bottom: 0px;
}
</style>

<style>
.dialogClass .el-dialog__body {
  padding: 12px 30px 0px 30px;
}

.dialogClass .el-collapse-item__content {
  padding-bottom: 0px;
}

.recentStatus {
  width: 10%;
  height: 12px;
  margin-right: 2px;
}

.recentStatus1 {
  background-color: #83ce42;
}

.recentStatus0 {
  background-color: #f15b5b;
}

.cronDes {
  font-size: 0.8em;
  color: #5e6d82;
  background-color: #f5f5f5;
  padding: 0 5px;
}
</style>